﻿using LibBinary.DataSource;
using LibBinary.FileData;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LibBinary.FileDeclaration.Binary
{
    public enum PrimitiveType
    {
        Boolean,
        Byte,
        Int16,
        Int32,
    }

    public class PrimitiveDeclaration : IFileDeclaration
    {
        private readonly PrimitiveType type;

        //TODO allow no-writing decl in text mode
        public PrimitiveDeclaration(PrimitiveType type)
        {
            this.type = type;
        }

        public AbstractFileData Read(BinaryFileSource src, AbstractFileData parentNode)
        {
            switch (type)
            {
                case PrimitiveType.Boolean:
                    return new PrimitiveData<bool>(parentNode) { Data = src.Read<byte>() != 0 };
                case PrimitiveType.Byte:
                    return new PrimitiveData<byte>(parentNode) { Data = src.Read<byte>() };
                case PrimitiveType.Int16:
                    return new PrimitiveData<short>(parentNode) { Data = src.Read<short>() };
                case PrimitiveType.Int32:
                    return new PrimitiveData<int>(parentNode) { Data = src.Read<int>() };
            }
            throw new ReadingFormatException("Unknown PrimitiveType in PrimitiveDeclaration.");
        }

        public void Write(BinaryFileSource src, AbstractFileData data)
        {
            switch (type)
            {
                case PrimitiveType.Boolean:
                    {
                        var cdata = data.As<PrimitiveData<bool>>();
                        if (cdata == null)
                        {
                            throw new WritingFormatException("Wrong data type.");
                        }
                        src.Write<byte>(cdata.Data ? (byte)1 : (byte)0);
                        break;
                    }
                case PrimitiveType.Byte:
                    {
                        var cdata = data.As<PrimitiveData<byte>>();
                        if (cdata == null)
                        {
                            throw new WritingFormatException("Wrong data type.");
                        }
                        src.Write<byte>(cdata.Data);
                        break;
                    }
                case PrimitiveType.Int16:
                    {
                        var cdata = data.As<PrimitiveData<short>>();
                        if (cdata == null)
                        {
                            throw new WritingFormatException("Wrong data type.");
                        }
                        src.Write<short>(cdata.Data);
                        break;
                    }
                case PrimitiveType.Int32:
                    {
                        var cdata = data.As<PrimitiveData<int>>();
                        if (cdata == null)
                        {
                            throw new WritingFormatException("Wrong data type.");
                        }
                        src.Write<int>(cdata.Data);
                        break;
                    }
                default:
                    throw new ReadingFormatException("Unknown PrimitiveType in PrimitiveDeclaration.");
            }
        }
    }
}
